using System;
using System.Collections.Generic;
using System.Text;

namespace OracleInternal.SqlAndPlsqlParser
{
	internal class Earley : Parser
	{
		protected class EarleyParsingHelper : ParsingHelper
		{
			protected EarleyParserGrammarDefinition m_vEarleyParserGrammar;

			protected Dictionary<int, FlexibleSizeLongArray>[] m_vWikiMatrix;

			protected Dictionary<int, FlexibleSizeLongArray> m_vCurrentMatrixCell;

			protected FlexibleSizeLongArray[] m_vPredictionMatrix;

			protected int m_vInputPosition;

			protected LexerToken m_vActivePositionLexerToken;

			protected LexerToken m_vActivePositionLookAheadLexerToken;

			protected int m_vActivePositionSymbolIndex = -1;

			protected int m_vActivePositionLookAheadSymbolIndex = -1;

			protected bool m_vActivePositionSymbolCouldBeIdentifier;

			protected bool m_vActivePositionLookAheadSymbolCouldBeIdentifier;

			protected HashSet<long> m_vStatesMarkedForCompletion = new HashSet<long>();

			protected Queue<long> m_vStatesToComplete = new Queue<long>(256);

			protected HashSet<long> m_vPredictionTuples = new HashSet<long>();

			protected int m_vIdentifierSymbolIndex;

			protected long m_vIdentifierSymbolIndexMask;

			protected long m_vIdentifierSymbolIndexMask1;

			protected HashSet<int> m_vPredictedSymbols = new HashSet<int>();

			public EarleyParsingHelper(string scriptText, List<LexerToken> lexerTokens, EarleyParserGrammarDefinition grammar)
				: base(scriptText, lexerTokens)
			{
				m_vEarleyParserGrammar = grammar;
				m_vIdentifierSymbolIndex = ((OracleSqlEarleyParserGrammarDefinition)m_vEarleyParserGrammar).m_vIdentifierSymbolIndex;
				m_vIdentifierSymbolIndexMask = (long)m_vIdentifierSymbolIndex << 32;
				m_vIdentifierSymbolIndexMask1 = m_vIdentifierSymbolIndexMask + 4294967296L;
			}

			public void Parse()
			{
				int count = m_vLexerTokens.Count;
				HashSet<int>[] vHasPathToFirstSymbolTable = m_vEarleyParserGrammar.m_vHasPathToFirstSymbolTable;
				m_vWikiMatrix = new Dictionary<int, FlexibleSizeLongArray>[count + 1];
				m_vPredictionMatrix = new FlexibleSizeLongArray[count + 1];
				m_vActivePositionLexerToken = m_vLexerTokens[0];
				m_vEarleyParserGrammar.GetTokensInfo(m_vActivePositionLexerToken, out m_vActivePositionSymbolIndex, out m_vActivePositionSymbolCouldBeIdentifier);
				if (count > 1)
				{
					m_vActivePositionLookAheadLexerToken = m_vLexerTokens[1];
					m_vEarleyParserGrammar.GetTokensInfo(m_vActivePositionLookAheadLexerToken, out m_vActivePositionLookAheadSymbolIndex, out m_vActivePositionLookAheadSymbolCouldBeIdentifier);
				}
				else
				{
					m_vActivePositionLookAheadLexerToken = null;
					m_vActivePositionLookAheadSymbolIndex = -1;
					m_vActivePositionLookAheadSymbolCouldBeIdentifier = false;
				}
				foreach (int vTopLevelSymbol in m_vEarleyParserGrammar.m_vTopLevelSymbols)
				{
					HashSet<int> hashSet = vHasPathToFirstSymbolTable[vTopLevelSymbol];
					if (hashSet.Contains(m_vActivePositionSymbolIndex))
					{
						m_vPredictionTuples.Add(((long)vTopLevelSymbol << 32) | (uint)m_vActivePositionSymbolIndex);
					}
					if (m_vActivePositionSymbolCouldBeIdentifier && hashSet.Contains(m_vIdentifierSymbolIndex))
					{
						m_vPredictionTuples.Add(((long)vTopLevelSymbol << 32) | (uint)m_vIdentifierSymbolIndex);
					}
				}
				m_vCurrentMatrixCell = new Dictionary<int, FlexibleSizeLongArray>(16);
				m_vWikiMatrix[0] = m_vCurrentMatrixCell;
				Predict();
				m_vPredictionTuples.Clear();
				Scan();
				for (m_vInputPosition = 1; m_vInputPosition < count; m_vInputPosition++)
				{
					m_vActivePositionLexerToken = m_vActivePositionLookAheadLexerToken;
					m_vActivePositionSymbolIndex = m_vActivePositionLookAheadSymbolIndex;
					m_vActivePositionSymbolCouldBeIdentifier = m_vActivePositionLookAheadSymbolCouldBeIdentifier;
					if (m_vInputPosition < count - 1)
					{
						m_vActivePositionLookAheadLexerToken = m_vLexerTokens[m_vInputPosition + 1];
						m_vEarleyParserGrammar.GetTokensInfo(m_vActivePositionLookAheadLexerToken, out m_vActivePositionLookAheadSymbolIndex, out m_vActivePositionLookAheadSymbolCouldBeIdentifier);
					}
					else
					{
						m_vActivePositionLookAheadLexerToken = null;
						m_vActivePositionLookAheadSymbolIndex = -1;
						m_vActivePositionLookAheadSymbolCouldBeIdentifier = false;
					}
					m_vCurrentMatrixCell = m_vWikiMatrix[m_vInputPosition];
					Complete();
					Predict();
					m_vStatesToComplete.Clear();
					m_vStatesMarkedForCompletion.Clear();
					m_vPredictionTuples.Clear();
					Scan();
				}
				m_vCurrentMatrixCell = m_vWikiMatrix[m_vInputPosition];
				Complete();
			}

			protected void HandleScanError()
			{
				int num = m_vInputPosition - 20;
				if (num < 0)
				{
					num = 0;
				}
				int vInputPosition = m_vInputPosition;
				int count = m_vLexerTokens.Count;
				int num2 = num + 40;
				if (num2 >= count)
				{
					num2 = count - 1;
				}
				num = m_vLexerTokens[num].m_vBegin;
				num2 = m_vLexerTokens[num2].m_vEnd;
				vInputPosition = m_vLexerTokens[vInputPosition].m_vBegin - num;
				string text = m_vScriptText.Substring(num, num2 - num);
				StringBuilder stringBuilder = new StringBuilder();
				for (int i = 0; i < vInputPosition; i++)
				{
					char c = text[i];
					if (char.IsControl(c) || char.IsWhiteSpace(c))
					{
						stringBuilder.Append(c);
					}
					else
					{
						stringBuilder.Append(' ');
					}
				}
				stringBuilder.Append('^');
				for (int i = vInputPosition + 1; i < text.Length; i++)
				{
					char c = text[i];
					if (char.IsControl(c) || char.IsWhiteSpace(c))
					{
						stringBuilder.Append(c);
					}
					else
					{
						stringBuilder.Append(' ');
					}
				}
				string text2 = stringBuilder.ToString();
				stringBuilder.Clear();
				char[] separator = new char[1]
				{
					'\n'
				};
				string[] array = text.Split(separator);
				string[] array2 = text2.Split(separator);
				stringBuilder.Append(">>>\n");
				for (int i = 0; i < array.Length; i++)
				{
					stringBuilder.Append(array[i]);
					stringBuilder.Append('\n');
					stringBuilder.Append(array2[i]);
					stringBuilder.Append('\n');
				}
				stringBuilder.Append(">>>\n");
				int[] expectedTokens = GetExpectedTokens();
				stringBuilder.Append("Possible follow up tokens are: \n");
				int[] array3 = expectedTokens;
				foreach (int num3 in array3)
				{
					stringBuilder.Append('\t');
					stringBuilder.Append(m_vEarleyParserGrammar.m_vAllSymbols[num3]);
					stringBuilder.Append('\n');
				}
				if (expectedTokens.Length > 20)
				{
					stringBuilder.Append("\t...\n");
				}
				text = string.Format(OracleScParserErrorStrings.GetErrorString(ParserExceptionError.NoParseFollowUp), m_vActivePositionLexerToken.m_vContent, stringBuilder.ToString());
				throw new ParserException(ParserExceptionType.Parser, ParserExceptionError.NoParseFollowUp, text);
			}

			protected int[] GetExpectedTokens()
			{
				Dictionary<int, int> dictionary = new Dictionary<int, int>();
				foreach (KeyValuePair<int, FlexibleSizeLongArray> item in m_vWikiMatrix[m_vInputPosition])
				{
					int key = item.Key;
					if (key < 0)
					{
						continue;
					}
					if (m_vEarleyParserGrammar.IsTerminal(key))
					{
						if (dictionary.ContainsKey(key))
						{
							dictionary[key]++;
						}
						else
						{
							dictionary[key] = 1;
						}
						continue;
					}
					foreach (int item2 in m_vEarleyParserGrammar.m_vHasPathToFirstSymbolTable[key])
					{
						if (dictionary.ContainsKey(item2))
						{
							dictionary[item2]++;
						}
						else
						{
							dictionary[item2] = 1;
						}
					}
				}
				int count = dictionary.Count;
				if (count > 0)
				{
					long[] array = new long[count];
					int[] array2 = new int[count];
					int num = 0;
					foreach (KeyValuePair<int, int> item3 in dictionary)
					{
						array[num++] = ((long)(-item3.Value) << 32) + item3.Key;
					}
					Array.Sort(array);
					for (num = 0; num < count; num++)
					{
						array2[num] = (int)(array[num] & 0xFFFFFFFFu);
					}
					return array2;
				}
				return new int[0];
			}

			protected void Predict()
			{
				FlexibleSizeLongArray flexibleSizeLongArray = null;
				FlexibleSizeLongArray value = null;
				Dictionary<long, FlexibleSizeLongArray> vPredictionsTable = m_vEarleyParserGrammar.m_vPredictionsTable;
				foreach (long vPredictionTuple in m_vPredictionTuples)
				{
					if (vPredictionsTable.TryGetValue(vPredictionTuple, out value))
					{
						flexibleSizeLongArray = FlexibleSizeLongArray.Merge(flexibleSizeLongArray, value);
					}
				}
				if (flexibleSizeLongArray != null)
				{
					m_vPredictionMatrix[m_vInputPosition] = flexibleSizeLongArray;
				}
			}

			protected bool Scan()
			{
				long[] array = null;
				long[] array2 = null;
				int num = 0;
				FlexibleSizeLongArray flexibleSizeLongArray = null;
				FlexibleSizeLongArray flexibleSizeLongArray2 = null;
				FlexibleSizeLongArray flexibleSizeLongArray3 = null;
				bool flag = false;
				Dictionary<int, FlexibleSizeLongArray> dictionary = new Dictionary<int, FlexibleSizeLongArray>(5);
				m_vCurrentMatrixCell.TryGetValue(m_vActivePositionSymbolIndex, out var value);
				if (m_vActivePositionSymbolCouldBeIdentifier && m_vCurrentMatrixCell.TryGetValue(m_vIdentifierSymbolIndex, out var value2))
				{
					value = FlexibleSizeLongArray.Merge(value, value2);
				}
				if (value != null)
				{
					num = value.m_vContentSize;
					array = value.m_vArray;
					for (int i = 0; i < num; i++)
					{
						long num2 = array[i];
						num2++;
						int num3 = (int)num2;
						int[] vRhs = m_vEarleyParserGrammar.m_vRules[num3 >> 12].m_vRhs;
						num3 &= 0xFFF;
						if (num3 >= vRhs.Length)
						{
							m_vStatesMarkedForCompletion.Add(num2);
							m_vStatesToComplete.Enqueue(num2);
							flexibleSizeLongArray = FlexibleSizeLongArray.Append(flexibleSizeLongArray, num2);
							continue;
						}
						int num4 = vRhs[num3];
						if (m_vEarleyParserGrammar.IsTerminal(num4))
						{
							if (num4 == m_vActivePositionLookAheadSymbolIndex)
							{
								flexibleSizeLongArray2 = FlexibleSizeLongArray.Append(flexibleSizeLongArray2, num2);
							}
							else if (m_vActivePositionLookAheadSymbolCouldBeIdentifier && num4 == m_vIdentifierSymbolIndex)
							{
								flexibleSizeLongArray3 = FlexibleSizeLongArray.Append(flexibleSizeLongArray3, num2);
							}
							continue;
						}
						HashSet<int> hashSet = m_vEarleyParserGrammar.m_vHasPathToFirstSymbolTable[num4];
						flag = false;
						if (hashSet.Contains(m_vActivePositionLookAheadSymbolIndex))
						{
							m_vPredictionTuples.Add(((long)num4 << 32) | (uint)m_vActivePositionLookAheadSymbolIndex);
							flag = true;
						}
						if (m_vActivePositionLookAheadSymbolCouldBeIdentifier && hashSet.Contains(m_vIdentifierSymbolIndex))
						{
							m_vPredictionTuples.Add(((long)num4 << 32) | (uint)m_vIdentifierSymbolIndex);
							flag = true;
						}
						if (flag)
						{
							dictionary.TryGetValue(num4, out value2);
							dictionary[num4] = FlexibleSizeLongArray.Append(value2, num2);
						}
					}
				}
				value = m_vPredictionMatrix[m_vInputPosition];
				if (value != null)
				{
					num = value.m_vContentSize;
					array2 = value.m_vArray;
					long num5 = (long)m_vInputPosition << 32;
					long num6 = (long)m_vActivePositionSymbolIndex << 32;
					long num7 = num6 + 4294967296L;
					int num8 = Array.BinarySearch(array2, 0, num, num6);
					if (num8 < 0)
					{
						num8 = ~num8;
					}
					for (int j = num8; j < num; j++)
					{
						long num2 = array2[j];
						if (num2 >= num7)
						{
							break;
						}
						num2 = num5 | (num2 & 0xFFFFFFFFu);
						num2++;
						int[] vRhs = m_vEarleyParserGrammar.m_vRules[(int)num2 >> 12].m_vRhs;
						if (1 == vRhs.Length)
						{
							m_vStatesMarkedForCompletion.Add(num2);
							m_vStatesToComplete.Enqueue(num2);
							flexibleSizeLongArray = FlexibleSizeLongArray.Insert(flexibleSizeLongArray, num2);
							continue;
						}
						int num4 = vRhs[1];
						if (m_vEarleyParserGrammar.IsTerminal(num4))
						{
							if (num4 == m_vActivePositionLookAheadSymbolIndex)
							{
								flexibleSizeLongArray2 = FlexibleSizeLongArray.Insert(flexibleSizeLongArray2, num2);
							}
							else if (m_vActivePositionLookAheadSymbolCouldBeIdentifier && num4 == m_vIdentifierSymbolIndex)
							{
								flexibleSizeLongArray3 = FlexibleSizeLongArray.Insert(flexibleSizeLongArray3, num2);
							}
							continue;
						}
						HashSet<int> hashSet = m_vEarleyParserGrammar.m_vHasPathToFirstSymbolTable[num4];
						flag = false;
						if (hashSet.Contains(m_vActivePositionLookAheadSymbolIndex))
						{
							m_vPredictionTuples.Add(((long)num4 << 32) | (uint)m_vActivePositionLookAheadSymbolIndex);
							flag = true;
						}
						if (m_vActivePositionLookAheadSymbolCouldBeIdentifier && hashSet.Contains(m_vIdentifierSymbolIndex))
						{
							m_vPredictionTuples.Add(((long)num4 << 32) | (uint)m_vIdentifierSymbolIndex);
							flag = true;
						}
						if (flag)
						{
							dictionary.TryGetValue(num4, out value2);
							dictionary[num4] = FlexibleSizeLongArray.Insert(value2, num2);
						}
					}
					if (m_vActivePositionSymbolCouldBeIdentifier)
					{
						num8 = Array.BinarySearch(array2, 0, num, m_vIdentifierSymbolIndexMask);
						if (num8 < 0)
						{
							num8 = ~num8;
						}
						for (int k = num8; k < num; k++)
						{
							long num2 = array2[k];
							if (num2 >= m_vIdentifierSymbolIndexMask1)
							{
								break;
							}
							num2 = num5 | (num2 & 0xFFFFFFFFu);
							num2++;
							int[] vRhs = m_vEarleyParserGrammar.m_vRules[(int)num2 >> 12].m_vRhs;
							if (1 == vRhs.Length)
							{
								m_vStatesMarkedForCompletion.Add(num2);
								m_vStatesToComplete.Enqueue(num2);
								flexibleSizeLongArray = FlexibleSizeLongArray.Insert(flexibleSizeLongArray, num2);
								continue;
							}
							int num4 = vRhs[1];
							if (m_vEarleyParserGrammar.IsTerminal(num4))
							{
								if (num4 == m_vActivePositionLookAheadSymbolIndex)
								{
									flexibleSizeLongArray2 = FlexibleSizeLongArray.Insert(flexibleSizeLongArray2, num2);
								}
								else if (m_vActivePositionLookAheadSymbolCouldBeIdentifier && num4 == m_vIdentifierSymbolIndex)
								{
									flexibleSizeLongArray3 = FlexibleSizeLongArray.Insert(flexibleSizeLongArray3, num2);
								}
								continue;
							}
							HashSet<int> hashSet = m_vEarleyParserGrammar.m_vHasPathToFirstSymbolTable[num4];
							flag = false;
							if (hashSet.Contains(m_vActivePositionLookAheadSymbolIndex))
							{
								m_vPredictionTuples.Add(((long)num4 << 32) | (uint)m_vActivePositionLookAheadSymbolIndex);
								flag = true;
							}
							if (m_vActivePositionLookAheadSymbolCouldBeIdentifier && hashSet.Contains(m_vIdentifierSymbolIndex))
							{
								m_vPredictionTuples.Add(((long)num4 << 32) | (uint)m_vIdentifierSymbolIndex);
								flag = true;
							}
							if (flag)
							{
								dictionary.TryGetValue(num4, out value2);
								dictionary[num4] = FlexibleSizeLongArray.Insert(value2, num2);
							}
						}
					}
				}
				if (flexibleSizeLongArray != null)
				{
					dictionary[-1] = flexibleSizeLongArray;
				}
				if (flexibleSizeLongArray2 != null)
				{
					dictionary[m_vActivePositionLookAheadSymbolIndex] = flexibleSizeLongArray2;
				}
				if (m_vActivePositionLookAheadSymbolCouldBeIdentifier && flexibleSizeLongArray3 != null)
				{
					dictionary[m_vIdentifierSymbolIndex] = flexibleSizeLongArray3;
				}
				if (dictionary.Count == 0)
				{
					HandleScanError();
				}
				m_vWikiMatrix[m_vInputPosition + 1] = dictionary;
				m_vCurrentMatrixCell = dictionary;
				return true;
			}

			protected void Complete()
			{
				ParserRuleTuple[] vRules = m_vEarleyParserGrammar.m_vRules;
				HashSet<int>[] vHasPathToFirstSymbolTable = m_vEarleyParserGrammar.m_vHasPathToFirstSymbolTable;
				bool flag = false;
				FlexibleSizeLongArray value = null;
				FlexibleSizeLongArray value2 = null;
				FlexibleSizeLongArray value3 = null;
				m_vCurrentMatrixCell.TryGetValue(-1, out value);
				m_vCurrentMatrixCell.TryGetValue(m_vActivePositionSymbolIndex, out value2);
				if (m_vActivePositionSymbolCouldBeIdentifier)
				{
					m_vCurrentMatrixCell.TryGetValue(m_vIdentifierSymbolIndex, out value3);
				}
				int num = m_vStatesToComplete.Count;
				while (num > 0)
				{
					long num2 = m_vStatesToComplete.Dequeue();
					num--;
					int num3 = (int)(num2 >> 32);
					Dictionary<int, FlexibleSizeLongArray> dictionary = m_vWikiMatrix[num3];
					int ruleHead = m_vEarleyParserGrammar.GetRuleHead(num2);
					FlexibleSizeLongArray flexibleSizeLongArray = m_vPredictionMatrix[num3];
					FlexibleSizeLongArray value4;
					if (flexibleSizeLongArray != null)
					{
						long[] vArray = flexibleSizeLongArray.m_vArray;
						long num4 = (long)ruleHead << 32;
						long num5 = num4 + 4294967296L;
						int vContentSize = flexibleSizeLongArray.m_vContentSize;
						int num6 = Array.BinarySearch(vArray, 0, vContentSize, num4);
						if (num6 < 0)
						{
							num6 = ~num6;
						}
						if (num6 < vContentSize && (vArray[num6] & num4) != 0L)
						{
							long num7 = (long)num3 << 32;
							for (int i = num6; i < vContentSize; i++)
							{
								num2 = vArray[i];
								if (num2 >= num5)
								{
									break;
								}
								num2++;
								int[] vRhs = vRules[(int)num2 >> 12].m_vRhs;
								num2 = num7 | (num2 & 0xFFFFFFFFu);
								int num8;
								if (vRhs.Length == 1)
								{
									num8 = -1;
									if (!m_vStatesMarkedForCompletion.Contains(num2))
									{
										m_vStatesMarkedForCompletion.Add(num2);
										m_vStatesToComplete.Enqueue(num2);
										value = FlexibleSizeLongArray.Insert(value, num2);
										num++;
									}
									continue;
								}
								num8 = vRhs[1];
								if (!m_vEarleyParserGrammar.IsTerminal(num8))
								{
									HashSet<int> hashSet = vHasPathToFirstSymbolTable[num8];
									flag = false;
									if (hashSet.Contains(m_vActivePositionSymbolIndex))
									{
										m_vPredictionTuples.Add(((long)num8 << 32) | (uint)m_vActivePositionSymbolIndex);
										flag = true;
									}
									if (m_vActivePositionSymbolCouldBeIdentifier && hashSet.Contains(m_vIdentifierSymbolIndex))
									{
										m_vPredictionTuples.Add(((long)num8 << 32) | (uint)m_vIdentifierSymbolIndex);
										flag = true;
									}
									if (flag)
									{
										m_vCurrentMatrixCell.TryGetValue(num8, out value4);
										m_vCurrentMatrixCell[num8] = FlexibleSizeLongArray.Insert(value4, num2);
									}
								}
								else if (num8 == m_vActivePositionSymbolIndex)
								{
									value2 = FlexibleSizeLongArray.Insert(value2, num2);
								}
								else if (m_vActivePositionSymbolCouldBeIdentifier && num8 == m_vIdentifierSymbolIndex)
								{
									value3 = FlexibleSizeLongArray.Insert(value3, num2);
								}
							}
						}
					}
					if (!dictionary.TryGetValue(ruleHead, out value4))
					{
						continue;
					}
					int vContentSize2 = value4.m_vContentSize;
					long[] vArray2 = value4.m_vArray;
					for (int j = 0; j < vContentSize2; j++)
					{
						num2 = vArray2[j];
						num2++;
						int num9 = (int)num2;
						int[] vRhs = vRules[num9 >> 12].m_vRhs;
						num9 &= 0xFFF;
						flag = false;
						int num8;
						if (num9 >= vRhs.Length)
						{
							num8 = -1;
							if (!m_vStatesMarkedForCompletion.Contains(num2))
							{
								m_vStatesMarkedForCompletion.Add(num2);
								m_vStatesToComplete.Enqueue(num2);
								value = FlexibleSizeLongArray.Insert(value, num2);
								num++;
							}
							continue;
						}
						num8 = vRhs[num9];
						if (!m_vEarleyParserGrammar.IsTerminal(num8))
						{
							HashSet<int> hashSet = vHasPathToFirstSymbolTable[num8];
							flag = false;
							if (hashSet.Contains(m_vActivePositionSymbolIndex))
							{
								m_vPredictionTuples.Add(((long)num8 << 32) | (uint)m_vActivePositionSymbolIndex);
								flag = true;
							}
							if (m_vActivePositionSymbolCouldBeIdentifier && hashSet.Contains(m_vIdentifierSymbolIndex))
							{
								m_vPredictionTuples.Add(((long)num8 << 32) | (uint)m_vIdentifierSymbolIndex);
								flag = true;
							}
							if (flag)
							{
								m_vCurrentMatrixCell.TryGetValue(num8, out value4);
								m_vCurrentMatrixCell[num8] = FlexibleSizeLongArray.Insert(value4, num2);
							}
						}
						else if (num8 == m_vActivePositionSymbolIndex)
						{
							value2 = FlexibleSizeLongArray.Insert(value2, num2);
						}
						else if (m_vActivePositionSymbolCouldBeIdentifier && num8 == m_vIdentifierSymbolIndex)
						{
							value3 = FlexibleSizeLongArray.Insert(value3, num2);
						}
					}
				}
				if (value != null)
				{
					m_vCurrentMatrixCell[-1] = value;
				}
				if (value2 != null)
				{
					m_vCurrentMatrixCell[m_vActivePositionSymbolIndex] = value2;
				}
				if (m_vActivePositionSymbolCouldBeIdentifier && value3 != null)
				{
					m_vCurrentMatrixCell[m_vIdentifierSymbolIndex] = value3;
				}
			}

			public ParseNode BuildParseTree()
			{
				Queue<EarleyParseTreeBuildState> queue = new Queue<EarleyParseTreeBuildState>(256);
				ParserRuleTuple parserRuleTuple = null;
				ParseNode parseNode = null;
				ParseNode parseNode2 = null;
				long num = 0L;
				int num2 = 0;
				int num3 = 0;
				int num4 = 0;
				try
				{
					int count = m_vLexerTokens.Count;
					if (count == 0)
					{
						return new ParseNode(0, count, -1, -1);
					}
					if (!m_vWikiMatrix[count].TryGetValue(-1, out var value) || value.m_vContentSize == 0)
					{
						throw new ParserException(ParserExceptionType.Parser, ParserExceptionError.ParseTreeBuildError, "Parse tree build: no suitable branches");
					}
					long[] vArray = value.m_vArray;
					int vContentSize = value.m_vContentSize;
					int[] vSymbolsFlags = m_vEarleyParserGrammar.m_vSymbolsFlags;
					for (int num5 = vContentSize - 1; num5 >= 0; num5--)
					{
						num = vArray[num5];
						int dot = (int)num & 0xFFF;
						int num6 = (int)num >> 12;
						ParserRuleTuple parserRuleTuple2 = m_vEarleyParserGrammar.m_vRules[num6];
						if ((vSymbolsFlags[parserRuleTuple2.m_vHead] & 6) == 2)
						{
							parseNode2 = new ParseNode(0, count, parserRuleTuple2.m_vHead, parserRuleTuple2.m_vHead);
							parseNode2.AppendUsedRule(num6);
							queue.Enqueue(new EarleyParseTreeBuildState(0, count, num6, dot, parserRuleTuple2, parseNode2));
							break;
						}
					}
					while (queue.Count != 0)
					{
						EarleyParseTreeBuildState earleyParseTreeBuildState = queue.Dequeue();
						ParserRuleTuple parserRuleTuple2 = earleyParseTreeBuildState.m_vRule;
						int dot = earleyParseTreeBuildState.m_vDot;
						int num6 = earleyParseTreeBuildState.m_vRuleIdx;
						int num7 = parserRuleTuple2.m_vRhs[dot - 1];
						int num8 = earleyParseTreeBuildState.m_vEnd - 1;
						_ = parserRuleTuple2.m_vHead;
						int num9 = parserRuleTuple2.m_vRhs.Length;
						long value2 = ((long)earleyParseTreeBuildState.m_vStart << 32) + ((long)earleyParseTreeBuildState.m_vRuleIdx << 12) + earleyParseTreeBuildState.m_vDot - 1;
						if (m_vEarleyParserGrammar.IsTerminal(num7))
						{
							if (num9 == 1)
							{
								earleyParseTreeBuildState.m_vParentNode.PayloadIn = num7;
								continue;
							}
							if (dot == 1)
							{
								earleyParseTreeBuildState.m_vParentNode.AddChild(new ParseNode(num8, earleyParseTreeBuildState.m_vEnd, num7, num7));
								continue;
							}
							earleyParseTreeBuildState.m_vParentNode.AddChild(new ParseNode(num8, earleyParseTreeBuildState.m_vEnd, num7, num7));
							earleyParseTreeBuildState.m_vEnd = num8;
							earleyParseTreeBuildState.m_vDot = dot - 1;
							queue.Enqueue(earleyParseTreeBuildState);
							continue;
						}
						if (m_vWikiMatrix[earleyParseTreeBuildState.m_vEnd].TryGetValue(-1, out value))
						{
							vArray = value.m_vArray;
							int num5;
							for (num5 = value.m_vContentSize - 1; num5 >= 0; num5--)
							{
								num = vArray[num5];
								if (num < 0)
								{
									continue;
								}
								num3 = (int)num >> 12;
								parserRuleTuple = m_vEarleyParserGrammar.m_vRules[num3];
								if (parserRuleTuple.m_vHead != num7)
								{
									continue;
								}
								num4 = (int)(num >> 32);
								if (dot == 1)
								{
									if (num4 != earleyParseTreeBuildState.m_vStart)
									{
										continue;
									}
								}
								else if (m_vWikiMatrix[num4].TryGetValue(num7, out value) && Array.BinarySearch(value.m_vArray, 0, value.m_vContentSize, value2) < 0)
								{
									continue;
								}
								num2 = (int)num & 0xFFF;
								vArray[num5] = -num;
								break;
							}
							if (num5 == -1)
							{
								throw new ParserException(ParserExceptionType.Parser, ParserExceptionError.ParseTreeBuildError, "Parse tree build: no matching completed state found");
							}
							if (num9 == 1)
							{
								earleyParseTreeBuildState.m_vParentNode.AppendUsedRule(num3);
								earleyParseTreeBuildState.m_vParentNode.PayloadIn = num7;
								earleyParseTreeBuildState.m_vRuleIdx = num3;
								earleyParseTreeBuildState.m_vDot = num2;
								earleyParseTreeBuildState.m_vRule = parserRuleTuple;
								queue.Enqueue(earleyParseTreeBuildState);
							}
							else if (dot == 1)
							{
								parseNode = new ParseNode(earleyParseTreeBuildState.m_vStart, earleyParseTreeBuildState.m_vEnd, num7, num7);
								parseNode.AppendUsedRule(num3);
								earleyParseTreeBuildState.m_vParentNode.AddChild(parseNode);
								earleyParseTreeBuildState.m_vRuleIdx = num3;
								earleyParseTreeBuildState.m_vRule = parserRuleTuple;
								earleyParseTreeBuildState.m_vDot = num2;
								earleyParseTreeBuildState.m_vParentNode = parseNode;
								queue.Enqueue(earleyParseTreeBuildState);
							}
							else
							{
								parseNode = new ParseNode(num4, earleyParseTreeBuildState.m_vEnd, num7, num7);
								parseNode.AppendUsedRule(num3);
								earleyParseTreeBuildState.m_vParentNode.AddChild(parseNode);
								EarleyParseTreeBuildState item = new EarleyParseTreeBuildState(num4, earleyParseTreeBuildState.m_vEnd, num3, num2, parserRuleTuple, parseNode);
								earleyParseTreeBuildState.m_vEnd = num4;
								earleyParseTreeBuildState.m_vDot = dot - 1;
								queue.Enqueue(earleyParseTreeBuildState);
								queue.Enqueue(item);
							}
							continue;
						}
						throw new ParserException(ParserExceptionType.Parser, ParserExceptionError.ParseTreeBuildError, "Parse tree build: completed states not found");
					}
					return parseNode2;
				}
				catch (Exception ex)
				{
					throw ex;
				}
			}

			public ParseNode BuildParseTreeRecursive()
			{
				try
				{
					ParseNode parseNode = null;
					int count = m_vLexerTokens.Count;
					if (count == 0)
					{
						return new ParseNode(0, count, -1, -1);
					}
					if (!m_vWikiMatrix[count].TryGetValue(-1, out var value) || value.m_vContentSize == 0)
					{
						throw new ParserException(ParserExceptionType.Parser, ParserExceptionError.ParseTreeBuildError, "Parse tree build: no suitable branches");
					}
					long[] vArray = value.m_vArray;
					int vContentSize = value.m_vContentSize;
					int[] vSymbolsFlags = m_vEarleyParserGrammar.m_vSymbolsFlags;
					for (int num = vContentSize - 1; num >= 0; num--)
					{
						long num2 = vArray[num];
						int dot = (int)num2 & 0xFFF;
						int num3 = (int)num2 >> 12;
						ParserRuleTuple parserRuleTuple = m_vEarleyParserGrammar.m_vRules[num3];
						if ((vSymbolsFlags[parserRuleTuple.m_vHead] & 6) == 2)
						{
							parseNode = new ParseNode(0, count, parserRuleTuple.m_vHead, parserRuleTuple.m_vHead);
							parseNode.AppendUsedRule(num3);
							try
							{
								BuildParseTree(0, count, num3, dot, parserRuleTuple, parseNode);
							}
							catch (ParserException)
							{
							}
						}
					}
					return parseNode;
				}
				catch (Exception ex2)
				{
					throw ex2;
				}
			}

			protected void BuildParseTree(int start, int end, int ruleIdx, int dot, ParserRuleTuple rt, ParseNode parent)
			{
				int num = rt.m_vRhs[dot - 1];
				int dot2 = 0;
				int num2 = 0;
				int num3 = 0;
				ParserRuleTuple parserRuleTuple = null;
				ParseNode parseNode = null;
				long value = ((long)start << 32) + ((long)ruleIdx << 12) + dot - 1;
				if (m_vEarleyParserGrammar.IsTerminal(num))
				{
					if (rt.m_vRhs.Length == 1)
					{
						parent.PayloadIn = num;
						return;
					}
					if (dot == 1)
					{
						parent.AddChild(new ParseNode(end - 1, end, num, num));
						return;
					}
					parent.AddChild(new ParseNode(end - 1, end, num, num));
					BuildParseTree(start, end - 1, ruleIdx, dot - 1, rt, parent);
					return;
				}
				if (m_vWikiMatrix[end].TryGetValue(-1, out var value2))
				{
					long[] vArray = value2.m_vArray;
					int num4;
					for (num4 = value2.m_vContentSize - 1; num4 >= 0; num4--)
					{
						long num5 = vArray[num4];
						if (num5 < 0)
						{
							continue;
						}
						num2 = (int)num5 >> 12;
						parserRuleTuple = m_vEarleyParserGrammar.m_vRules[num2];
						if (parserRuleTuple.m_vHead != num)
						{
							continue;
						}
						num3 = (int)(num5 >> 32);
						if (dot == 1)
						{
							if (num3 != start)
							{
								continue;
							}
						}
						else if (m_vWikiMatrix[num3].TryGetValue(num, out value2) && Array.BinarySearch(value2.m_vArray, 0, value2.m_vContentSize, value) < 0)
						{
							continue;
						}
						dot2 = (int)num5 & 0xFFF;
						vArray[num4] = -num5;
						break;
					}
					if (num4 == -1)
					{
						throw new ParserException(ParserExceptionType.Parser, ParserExceptionError.ParseTreeBuildError, "Parse tree build: no matching completed state found");
					}
					if (rt.m_vRhs.Length == 1)
					{
						parent.AppendUsedRule(num2);
						parent.PayloadIn = num;
						BuildParseTree(start, end, num2, dot2, parserRuleTuple, parent);
					}
					else if (dot == 1)
					{
						parseNode = new ParseNode(start, end, num, num);
						parseNode.AppendUsedRule(num2);
						parent.AddChild(parseNode);
						BuildParseTree(start, end, num2, dot2, parserRuleTuple, parseNode);
					}
					else
					{
						parseNode = new ParseNode(num3, end, num, num);
						parseNode.AppendUsedRule(num2);
						parent.AddChild(parseNode);
						BuildParseTree(num3, end, num2, dot2, parserRuleTuple, parseNode);
						BuildParseTree(start, num3, ruleIdx, dot - 1, rt, parent);
					}
					return;
				}
				throw new ParserException(ParserExceptionType.Parser, ParserExceptionError.ParseTreeBuildError, "Parse tree build: completed states not found");
			}

			public override string ToString()
			{
				StringBuilder stringBuilder = new StringBuilder();
				int num = 50;
				for (int i = 0; i < m_vWikiMatrix.Length; i++)
				{
					Dictionary<int, FlexibleSizeLongArray>.KeyCollection keys = m_vWikiMatrix[i].Keys;
					int[] array = new int[keys.Count];
					keys.CopyTo(array, 0);
					Array.Sort(array);
					foreach (int num2 in array)
					{
						long[] vArray = m_vWikiMatrix[i][num2].m_vArray;
						stringBuilder.Append('[');
						stringBuilder.Append(i);
						stringBuilder.Append(',');
						stringBuilder.Append(num2);
						stringBuilder.Append(')');
						for (int k = 0; k < vArray.Length && k < num + 1; k++)
						{
							long num3 = vArray[k];
							int num4 = (int)num3;
							int pos = (int)(num3 >> 32) & 0xFFFF;
							stringBuilder.Append(m_vEarleyParserGrammar.m_vRules[num4].ToString(pos));
							if (k == num)
							{
								stringBuilder.Append(" ... " + vArray.Length + " more states");
							}
						}
						stringBuilder.Append('\n');
					}
				}
				return stringBuilder.ToString();
			}
		}

		protected EarleyParserGrammarDefinition m_vEarleyParserGrammar;

		public EarleyParserGrammarDefinition EarleyGrammar => m_vEarleyParserGrammar;

		public Earley(EarleyParserGrammarDefinition grammarDefinition)
		{
			m_vEarleyParserGrammar = grammarDefinition;
		}

		public override ParseNode Parse(string scriptText, List<LexerToken> src)
		{
			if (src.Count < 1)
			{
				return null;
			}
			EarleyParsingHelper earleyParsingHelper;
			using (new PerformanceTimer("Parse"))
			{
				earleyParsingHelper = new EarleyParsingHelper(scriptText, src, m_vEarleyParserGrammar);
				earleyParsingHelper.Parse();
			}
			using (new PerformanceTimer("Build Parse Tree"))
			{
				return earleyParsingHelper.BuildParseTree();
			}
		}
	}
}
